
#include "unitIA.h"
#include "exceptions.h"
#include "gamemap.h"

#include "soundmanager.h"

#include <qdebug.h>

UnitIA::UnitIA(GameMap* map, const UnitProperties& properties, quint8 x , quint8 y , quint8 teamNumber) :
    Unit(map, properties, x, y, teamNumber)
{
    m_IAControlled = true;
    m_target = NULL;
}

void UnitIA::newTurn()
{
    Unit::newTurn();
    moveTo(0,0);
}

bool UnitIA::moveTo(quint8 x, quint8 y)    //returns true if the unit actually moved ; otherwise returns false
{
    //calls the path finder to retrieve the steps path and makes the unit walk along this path step by step
    QPoint dest = getDestination();
    x = dest.x();
    y = dest.y();
    const QList<QPoint> path = pathTowards(x, y);
    if(!path.isEmpty() && (x != m_x || y != m_y))
    {
        m_animation = path;
    }
    else
    {
        //No path found : don't move
    }

    m_remainingAction = false;

    return !path.isEmpty();
}

void UnitIA::attack(Unit* target)
{
    target = m_target;
    if(target != 0 && GameMap::taxicabDistance(m_x, m_y, target->getX(), target->getY()) == 1)
    {
        Unit::attack(target);
    }
}

QList<QPoint> UnitIA::pathTowards(quint8 x, quint8 y)
{
    QList<QPoint> path = m_map->findPath(QPoint(m_x, m_y), QPoint(x,y), m_properties.unitType, m_remainingMoves);
    if(path.isEmpty())
    {
        path = m_map->findPath(QPoint(m_x, m_y), QPoint(x, y), m_properties.unitType, 255, true);
        //truncates the inaccessible part of the path
        qint16 trunc = path.size() - m_remainingMoves;
        for(qint16 i = 0 ; i < trunc ; i++)
        {
            path.removeLast();
        }
        qint16 i = path.size()-1;
        QList<QPoint> tmpPath;
        if(i >= 0)
        {
            do {
                tmpPath = m_map->findPath(QPoint(m_x, m_y), path.at(i), m_properties.unitType, m_remainingMoves);
                i--;
            } while(tmpPath.isEmpty() && i >= 0);
        }
        path = tmpPath;
    }
    return path;
}

QPoint UnitIA::getDestination(){
    QPoint dest(m_x, m_y);

    const QList<Unit*>& units = m_map->getUnits();

    if (m_target == NULL)
    {
        qint32 pv = 0;

        for(quint8 i = 0 ; i < units.size() ; ++i)
        {
            if(!units.at(i)->isIAControlled() && GameMap::taxicabDistance(m_x, m_y, units.at(i)->getX(), units.at(i)->getY())
                && pv < units.at(i)->getProperties().health && !pathTowards(units.at(i)->getX(), units.at(i)->getY()).isEmpty())
            {
                pv = units.at(i)->getProperties().health;
                m_target = units.at(i);
            }
        }

        for (int i = 0; i < units.size(); ++i) {
            if (m_target == 0) {
            if (pv < units.at(i)->getProperties().health && units.at(i)->getTeamNumber() != m_team && !pathTowards(units.at(i)->getX(), units.at(i)->getY()).isEmpty()){
                pv = units.at(i)->getProperties().health;
                m_target = units.at(i);
            }
            }
        }
    }

    quint8 i = 0;
    while(m_target == 0 && i < units.size())
    {
        //if doesn't find any target, takes the first unit
        if(!units.at(i)->isIAControlled())
        {
            m_target = units.at(i);
        }
        i++;
    }
    if(m_target != NULL)
    {
        dest = QPoint(m_target->getX(), m_target->getY());
    }
    return dest;
}
